﻿using ArtMath.Attribute;
using ArtMath.Component.Interface;
using ArtMath.Component.Line;
using ArtMath.Component.Point;
using ArtMath.Converter;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Helper;
using ArtMath.Resource;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using ArtMath.CommonType;

namespace ArtMath.Component.Vector
{
    /// <summary>
    /// 向量基类
    /// </summary>
    [Serializable]
    public class VectorBase : LineSegmentBase, IDirectedAngle
    {
        double dirAngle;//, rotAngle;
        bool showPoints;
        PropertyDisplayer dirAngleDisplayer;
        public VectorBase(SketchPad pad, string name, ToolTypeName toolType, bool addToList = true) : base(pad, name, toolType, addToList)
        {
            DirectedAngleDisplayer = new PropertyDisplayer(this, "DirectedAngle");
        }
        [MultilingualDisplayName("StartPoint")]
        public override PointBase Point1
        {
            get
            {
                return base.Point1;
            }

            set
            {
                base.Point1 = value;
            }
        }
        [MultilingualDisplayName("TerminalPoint")]
        public override PointBase Point2
        {
            get
            {
                return base.Point2;
            }

            set
            {
                base.Point2 = value;
            }
        }
        [MultilingualCategory("Parameter"), MultilingualDisplayName("DirectedAngle"), TypeConverter(typeof(IntelliAngleConverter))]
        public double DirectedAngle
        {
            get { return dirAngle; }
            protected set
            {
                //rotAngle = Utility.GetRotatedAngle(dirAngle.GetUnitVector(), value.GetUnitVector());
                dirAngle = value;
                if (ToolType != ToolTypeName.ldxl)
                {
                    Slope = Math.Tan(dirAngle);
                }
            }
        }
        [MultilingualCategory(null, "Sketchpad", "Display"), MultilingualDisplayName(null, "DirectedAngle", "Displayer")]
        public PropertyDisplayer DirectedAngleDisplayer
        {
            get { return dirAngleDisplayer; }
            set { dirAngleDisplayer = value; }
        }
        public override double ArrivalAngle
        {
            get
            {
                return NewDirectedAngle;
            }
        }
        [MultilingualDisplayName("VecLength")]
        public override double Length
        {
            get
            {
                return base.Length;
            }

            protected set
            {
                base.Length = value;
            }
        }
        [MultilingualCategory("View"), MultilingualDisplayName(null, "Show", "EndPoint")]
        public bool ShowEndPoint
        {
            get { return showPoints; }
            set
            {
                showPoints = value;
                Point1.Visible = Point2.Visible = showPoints;
                Pad.Canvas.Invalidate();
            }
        }
        //[Browsable(false)]
        //public double NewPDirectedAngle
        //{
        //    get
        //    {
        //        return Point1.NewPxy.GetAngle(Point2.NewPxy);
        //    }
        //}
        [Browsable(false)]
        public virtual double NewDirectedAngle
        {
            get
            {
                return Point1.NewXY.GetAngle(Point2.NewXY);
            }
        }
        protected override Pen LinePen
        {
            get
            {
                Pen p = base.LinePen;
                p.CustomEndCap = new AdjustableArrowCap(5, 6, true);
                return p;
            }
        }
        //[Browsable(false)]
        //public double RotatedAngle
        //{
        //    get { return rotAngle; }
        //}
        public override void RefreshPropertyDisplayersLocation()
        {
            DirectedAngleDisplayer.RefreshLocation();
            base.RefreshPropertyDisplayersLocation();
        }
        public override void RefreshPropertyDisplayersText()
        {
            DirectedAngleDisplayer.RefreshText();
            base.RefreshPropertyDisplayersText();
        }
        public override void PaintProperties(Graphics gra)
        {
            if (ObjectState == ObjectState.Normal && Visible)
            {
                DirectedAngleDisplayer.Paint(gra);
            }
            base.PaintProperties(gra);
        }
        public override PropertyDisplayer[] PropertyDisplayersCheckNearBy(PointD Plocation)
        {
            List<PropertyDisplayer> res = new List<PropertyDisplayer>(base.PropertyDisplayersCheckNearBy(Plocation));
            if (DirectedAngleDisplayer.InRegion(Plocation))
            {
                res.Add(DirectedAngleDisplayer);
            }
            return res.ToArray();
        }
        public double ScalarProduct(VectorBase vector)
        {
            return Utility.ScalarProduct(Point1.ToPointD(), Point2.ToPointD(), vector.Point1.ToPointD(), vector.Point2.ToPointD());
        }
        public double CrossProduct(VectorBase vector)
        {
            return Utility.CrossProduct(Point1.ToPointD(), Point2.ToPointD(), vector.Point1.ToPointD(), vector.Point2.ToPointD());
        }
        protected override void OtherBuildingTransactions(PointD xy)
        {
            DirectedAngle = Point1.ToPointD().GetAngle(xy);
            ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}{Resources.LeftParenthesis}{string.Format(Resources.Translate("Of"), Resources.Translate("TerminalPoint"), Resources.Translate("Coordinate"))}{Resources.ColonSeparate}{Pad.PxyToMath(SpareCoordinate)}{Resources.CommaSeparate}{Resources.Translate("VecLength")} = {Length}{Resources.CommaSeparate}{Resources.Translate("DirectedAngle")} = {dirAngle}");
        }
        public override void PaintVirtualObjects(Graphics gra)
        {
            gra.DrawVector(Point1.Pxy, SpareCoordinate_);
            gra.DrawPoint(SpareCoordinate_);
        }
        public override void ComponentChanged(ShapeBase component)
        {
            DirectedAngle = NewDirectedAngle;
            base.ComponentChanged(component);
        }
    }
}
